package demo.platform;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathException;
import org.apache.xmlbeans.XmlObject;
import org.hp.systinet.http.BasicCredentials;
import org.hp.systinet.http.Credentials;
import org.hp.systinet.http.CredentialsList;
import org.hp.systinet.http.HTTPClient;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class RestClientDemo {

	private static final String ATOM_TASK_ARTIFACT = "taskArtifact/";
	
	private static final String UUID_SEP = ":";

	private static String[] taskUuids = {};

	private static CredentialsList credentialsList = null;
	private static Header[] headers = null;
	private static HttpState session = null;
	private static HttpConnectionManager pool = null;

	private static String endpointBase = null;
	private static String restAtomUri = null;
	private static String restAtomUriParams = "";
	private static String reportFilePath= null;
	private static BufferedWriter syncReportDataWritter=null;

	/**
	 * Initialize REST client.
	 */
	private static void initialize() throws Exception {
		// read demo properties
		endpointBase = DemoProperties.getProperty("shared.http.urlbase", "http://localhost:8080/soa");
		String user = DemoProperties.getProperty("platform.demos.user.name","admin");
		String password = DemoProperties.getProperty("platform.demos.user.password", "changeit");
		taskUuids = DemoProperties.getProperty("platform.demos.task.uuids").split(UUID_SEP);
		restAtomUri = DemoProperties.getProperty("platform.demos.url.rest.atom","/platfom/restSecure/artifact/");
		
		restAtomUriParams = DemoProperties.getProperty("platform.demos.url.rest.atom.parms","");
		if(restAtomUriParams == null) restAtomUriParams = "";
		reportFilePath = DemoProperties.getProperty("platform.demos.report.filepath","./data/syncReportData.html");

		credentialsList = new CredentialsList();
		String baseUrl = endpointBase + restAtomUri;
		Credentials credentials = new BasicCredentials(baseUrl, user, password);
		credentialsList.addCredentials(credentials);

		// Initialize report file
		File syncReportDataFile = new File(reportFilePath);
		if(!syncReportDataFile.exists()) {
			syncReportDataFile.createNewFile();
		}
		syncReportDataWritter = new BufferedWriter(new FileWriter(syncReportDataFile));
	}
	
	private static void startWriter()  throws Exception{
		syncReportDataWritter.write("<html><head><title>Synchronization Report</title></head><body>");
		syncReportDataWritter.write("<h1>Synchornization Report Details</h1>");
	}

	private static void endWriter()  throws Exception{
		syncReportDataWritter.write("</body></html>");	
		syncReportDataWritter.close();
	}
	
	private static void execute() throws Exception {
		startWriter();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.sss");
		
		for (String artifactUuid : taskUuids) {
			syncReportDataWritter.write("<h2>Task Artifact UUID:"+artifactUuid+"</h2>");
			String url = endpointBase + restAtomUri + ATOM_TASK_ARTIFACT + artifactUuid + restAtomUriParams;
			System.out.println("TASK ARTIFACT REST URL:");
			System.out.println("\t"+url);
			HttpMethod response = HTTPClient.doGet(url, credentialsList, headers, session, pool);
			XmlObject xmlResponse = XmlObject.Factory.parse(response.getResponseBodyAsStream());
			Node domNode = xmlResponse.getDomNode();
			JXPathContext context = JXPathContext.newContext(domNode);
			List<String> reportPaths = new ArrayList<String>();
			context.registerNamespace("baseNS", "http://www.w3.org/2005/Atom");
			context.registerNamespace("art", "http://hp.com/2008/02/systinet/platform/model/artifact");
			context.registerNamespace("p", "http://hp.com/2008/02/systinet/platform/model/property");
			context.registerNamespace("sdm", "http://hp.com/2007/10/systinet/platform/model/propertyType");
			context.registerNamespace("xlin", "http://www.w3.org/1999/xlink");
			System.out.println("SEARCHING...");
			List<Node> taskReports = context.selectNodes("/baseNS:entry/baseNS:content/art:artifact/p:taskReports[@sdm:type=\"documentRelationship\"]");
			if(taskReports != null) {
				for(Node taskReport: taskReports) {
					int num = taskReport.getAttributes().getLength();
					for(int i=0;i<num;i++) {
						Node attr = taskReport.getAttributes().item(i);
						if(attr.getNodeName().equals("xlin:href")) {
							reportPaths.add(attr.getNodeValue());
						}
					}
				}
				System.out.println("\t Found "+reportPaths.size()+ " synchronization reports...");
			}  else {
				System.out.println("No reports found.");
			}				
			
			String latestReportPath = null;
			Date latestTimeDate = null;
			String timestampStr = null;
			for(String reportPath: reportPaths) {
				// Find the latest report
				url = endpointBase + restAtomUri + reportPath + restAtomUriParams;
				response = HTTPClient.doGet(url, credentialsList, headers, session, pool);
				xmlResponse = XmlObject.Factory.parse(response.getResponseBodyAsStream());
				domNode = xmlResponse.getDomNode();
				context = JXPathContext.newContext(domNode);
				context.registerNamespace("baseNS", "http://www.w3.org/2005/Atom");
				timestampStr = (String)context.getValue("/baseNS:entry/baseNS:updated");
				Date timeDate = dateFormat.parse(timestampStr);
				System.out.println("TIMESTAMP: "+timeDate.toString());
				if(latestTimeDate == null || latestTimeDate.before(timeDate)) {
					latestTimeDate = timeDate;
					latestReportPath = reportPath;
				}
			}
			if(latestReportPath != null) {
				// Accessing data
				url = endpointBase + restAtomUri + latestReportPath + "/data";				
				System.out.println("\t LATEST REPORT ARTIFACT REST URL:");
				System.out.println("\t \t"+url);
				response = HTTPClient.doGet(url, credentialsList, headers, session, pool);
				xmlResponse = XmlObject.Factory.parse(response.getResponseBodyAsStream());
				domNode = xmlResponse.getDomNode();
				context = JXPathContext.newContext(domNode);
				context.registerNamespace("rr", "http://systinet.com/2005/05/soa/report");
				try {
					Node synchronizerNode = (Node)context.selectSingleNode("/rr:Synchronizer");
					int num = synchronizerNode.getAttributes().getLength();
					for(int i=0;i<num;i++) {
						Node attr = synchronizerNode.getAttributes().item(i);
						if(attr.getNodeName().equals("description")) {
							syncReportDataWritter.write("<h3>Synchronization Description: " + attr.getNodeValue() + "</h3>");
							break;
						}
					}
					List<Node> documentNodes = context.selectNodes("/rr:Synchronizer/rr:document");
					if(documentNodes.size()>0) {
						syncReportDataWritter.write("<table border=1 width=75%><tr><th bgcolor=#99CCCC><b>Artifact Name</b></th><th bgcolor=#99CCCC><b>Access Path</b></th><th bgcolor=#99CCCC><b>Desc</b></th><th bgcolor=#99CCCC><b>Status</b></th></tr>");
						for(Node documentNode:documentNodes) {
							num = documentNode.getAttributes().getLength();
							String artName="", artPath="", artDesc="", artStatus="";
							for(int i=0;i<num;i++) {
								Node attr = documentNode.getAttributes().item(i);
								if(attr.getNodeName().equals("artifactName")) {
									artName =  attr.getNodeValue();
								} else if(attr.getNodeName().equals("description")) {
									artDesc =  attr.getNodeValue();
								} else if(attr.getNodeName().equals("status")) {
									artStatus =  attr.getNodeValue();
								}
							}
							NodeList nodeList = documentNode.getChildNodes();
							for(int i=0;i<nodeList.getLength();i++) {
								if(nodeList.item(i).getNodeType() == Node.TEXT_NODE) {
									artPath = nodeList.item(i).getNodeValue();
									break;
								}
							}
							
							syncReportDataWritter.write("<tr><td>"+artName+"</td><td>"+artPath+"</td><td>"+artDesc+"</td><td>"+artStatus+"</td></tr>");
						}
						syncReportDataWritter.write("</table>");
					}
					
				} catch (JXPathException e) {
					// exception message
					context.registerNamespace("rest", "http://systinet.com/2005/05/soa/resource");
					Node exceptionNode = (Node)context.selectSingleNode("/rest:exception");
					String exceptionCode = null;
					String exceptionMessage = null;
					String exceptionStackTrace = null;
					
					if(exceptionNode != null) {
						Node codeNode = (Node)context.selectSingleNode("/rest:exception/rest:code");
						NodeList nodeList = codeNode.getChildNodes();
						for(int i=0;i<nodeList.getLength();i++) {
							if(nodeList.item(i).getNodeType() == Node.TEXT_NODE) {
								exceptionCode = nodeList.item(i).getNodeValue();
								break;
							}
						}
						
						Node messageNode = (Node)context.selectSingleNode("/rest:exception/rest:message");
						nodeList = messageNode.getChildNodes();
						for(int i=0;i<nodeList.getLength();i++) {
							if(nodeList.item(i).getNodeType() == Node.TEXT_NODE) {
								exceptionMessage = nodeList.item(i).getNodeValue();
								break;
							}
						}
						
						Node stackTraceNode = (Node)context.selectSingleNode("/rest:exception/rest:stackTrace");
						nodeList = stackTraceNode.getChildNodes();
						for(int i=0;i<nodeList.getLength();i++) {
							if(nodeList.item(i).getNodeType() == Node.TEXT_NODE) {
								exceptionStackTrace = nodeList.item(i).getNodeValue();
								break;
							}
						}
						syncReportDataWritter.write("<table border=1 width=75%>");
						syncReportDataWritter.write("<tr><td bgcolor=#99CCCC><b>Exception Code</b></td><td>"+exceptionCode+"</td></tr>");
						syncReportDataWritter.write("<tr><td bgcolor=#99CCCC><b>Exception Message</b></td><td>"+exceptionMessage+"</td></tr>");
						syncReportDataWritter.write("<tr><td bgcolor=#99CCCC><b>Exception StackTrace</b></td><td>"+exceptionStackTrace+"</td></tr>");
					} else {
						syncReportDataWritter.write("Unsupported Report!");
					}					
				}
			}
		}
		endWriter();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			initialize();
			execute();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
